/*-
 * Copyright (c) 2009 Jonathan Anderson
 * All rights reserved.
 *
 * WARNING: THIS IS EXPERIMENTAL SECURITY SOFTWARE THAT MUST NOT BE RELIED
 * ON IN PRODUCTION SYSTEMS.  IT WILL BREAK YOUR SOFTWARE IN NEW AND
 * UNEXPECTED WAYS.
 * 
 * This software was developed at the University of Cambridge Computer
 * Laboratory with support from a grant from Google, Inc. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef UA_CLIENT_REQUEST_H

#include <libuserangel.h>
#include <QString>

#include "UserAngel.h"

class Client;


/**
 * Represents a request from a client.
 *
 * A ClientRequest proceeds in two stages: first, readArguments() is called, in
 * which everything is read off the wire that needs to be. Then, after policy is
 * consulted to determine if the request is legal, run() is called. If not, the
 * socket should be in a sensible state (i.e. ready for the next request to be
 * read).
 *
 * If the request is permitted to proceed, run() will be called, in which the
 * ClientRequest should do its work and send responses as appropriate.
 */
class ClientRequest
{
	public:
	/**
	 * Find the right ClientRequest to serve a client's request.
	 *
	 * @note   the caller is responsible for deleting the request
	 */
	static ClientRequest* req(ua_request_t);


	//! Virtual destructor
	virtual ~ClientRequest() {}


	/**
	 * The name of the request.
	 *
	 * This should be something human-readable and preferably a CamelCased verb,
	 * e.g. OpenFile and CheckAccess.
	 */
	virtual QString name() const = 0;


	/**
	 * A human-readable representation.
	 *
	 * @return  some sensible representation of the request's arguments
	 *          (e.g. "path='/etc/passwd', mode=read-only)
	 */
	virtual QString argString() const = 0;


	/**
	 * Read everything that you are going to read from the client socket.
	 *
	 * @param   client      the client that you are servicing
	 * @param   first       the first datum that the client sent
	 */
	virtual void readArguments(Client* client, userAngel::UserAngel::Datum first) = 0;


	/**
	 * Perform the requested action and send appropriate responses.
	 *
	 * @param   client      the client to send the response to
	 *
	 * @throw   ClientFatalException    if the client needs to die
	 * @throw   Exception               for other kinds of problems
	 */
	virtual void run(Client*) = 0;
};

#define UA_CLIENT_REQUEST_H
#endif

